/*
 * Copyright (c) 2023, mdf Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-10-18     MacRsh       First version
 */

#ifndef MDF_DEF_H
#define MDF_DEF_H

#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mdf_config.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
* @version mdf version
*/
#define MDF_VERSION                     "0.0.1"

/**
 * @def Compiler related
 */
#if defined(__ARMCC_VERSION)
#define MDF_SECTION(x)              	__attribute__((section(x)))
#define MDF_USED                    	__attribute__((used))
#define MDF_WEAK                    	__attribute__((weak))
#define MDF_INLINE                  	static __inline
#elif defined (__IAR_SYSTEMS_ICC__)
#define MDF_SECTION(x)               	@ x
#define MDF_USED                     	__root
#define MDF_WEAK                     	__weak
#define MDF_INLINE                   	static inline
#elif defined (__GNUC__)
#define MDF_SECTION(x)                  __attribute__((section(x)))
#define MDF_USED                        __attribute__((used))
#define MDF_WEAK                        __attribute__((weak))
#define MDF_INLINE                      static __inline
#elif defined (__ADSPBLACKFIN__)
#define MDF_SECTION(x)               	__attribute__((section(x)))
#define MDF_USED                     	__attribute__((used))
#define MDF_WEAK                     	__attribute__((weak))
#define MDF_INLINE                   	static inline
#elif defined (_MSC_VER)
#define MDF_SECTION(x)
#define MDF_USED
#define MDF_WEAK
#define MDF_INLINE                   	static __inline
#elif defined (__TASKING__)
#define MDF_SECTION(x)               	__attribute__((section(x)))
#define MDF_USED                     	__attribute__((used, protect))
#define MDF_WEAK                     	__attribute__((weak))
#define MDF_INLINE                   	static inline
#endif

typedef int (*mdf_init_fn_t)(void);

/**
 * @def Auto-init export
 */
#define MDF_INIT_EXPORT(fn, level) \
    MDF_USED const mdf_init_fn_t _mdf_auto_init_##fn MDF_SECTION(".auto_init."level) = fn

/**
 * @def Board auto-init export
 */
#define MDF_INIT_BOARD_EXPORT(fn)       MDF_INIT_EXPORT(fn, "1")

/**
 * @def Driver auto-init export
 */
#define MDF_INIT_DRIVER_EXPORT(fn)      MDF_INIT_EXPORT(fn, "2")

/**
 * @def Device auto-init export
 */
#define MDF_INIT_DEVICE_EXPORT(fn)      MDF_INIT_EXPORT(fn, "3")

/**
 * @def Error code
 */
#define MDF_EOK                         (0)                         /* No error */
#define MDF_ENOMEM                      (-1)                        /* No enough memory */
#define MDF_EIO                         (-2)                        /* I/O error */
#define MDF_ENOTFOUND                   (-3)                        /* Not found */
#define MDF_EBUSY                       (-4)                        /* Resource busy */
#define MDF_EEXIST                      (-5)                        /* Exists */
#define MDF_ENOTSUP                     (-6)                        /* Operation not supported */
#define MDF_EINVAL                      (-7)                        /* Invalid argument */

/**
 * @struct Double list
 */
struct mdf_list
{
    struct mdf_list *next;                                          /* Point to next node */
    struct mdf_list *prev;                                          /* Point to prev node */
};

/**
 * @struct Ring buffer
 */
struct mdf_ringbuf
{
    uint8_t *buffer;                                             /* Buffer pool */
    uint16_t size;                                               /* Buffer pool size */
    uint16_t read_mirror: 1;                                     /* Read mirror flag */
    uint16_t write_mirror: 1;                                    /* Write mirror flag */
    uint16_t reserved: 14;                                       /* Reserved */
    uint16_t read_index;                                         /* Read index */
    uint16_t write_index;                                        /* Write index */
};

#define MDF_OFLAG_CLOSED                (0)
#define MDF_OFLAG_RDONLY                ((0x01) << 24)
#define MDF_OFLAG_WRONLY                ((0x02) << 24)
#define MDF_OFLAG_RDWR                  ((0x03) << 24)
#define MDF_OFLAG_NONBLOCK              ((0x04) << 24)

#define MDF_SFLAG_CLOSED                MDF_OFLAG_CLOSED
#define MDF_SFLAG_RDONLY                MDF_OFLAG_RDONLY
#define MDF_SFLAG_WRONLY                MDF_OFLAG_WRONLY
#define MDF_SFLAG_RDWR                  MDF_OFLAG_RDWR
#define MDF_SFLAG_NONBLOCK              MDF_OFLAG_NONBLOCK
#define MDF_SFLAG_NODRV                 ((0x10) << 24)

enum mdf_dev_type
{
    Mdf_Dev_Type_Gpio = 0,
    Mdf_Dev_Type_Spi,
    Mdf_Dev_Type_I2c,
    Mdf_Dev_Type_Uart,
    Mdf_Dev_Type_Adc,
    Mdf_Dev_Type_Dac,
    Mdf_Dev_Type_Timer,
    Mdf_Dev_Type_Pwm,
};

struct mdf_dev;

struct mdf_drv
{
    void *data;
    void *ops;
};

struct mdf_dev_ops
{
    int (*open)(struct mdf_dev *dev);
    int (*close)(struct mdf_dev *dev);
    ssize_t (*read)(struct mdf_dev *dev, int off, void *buf, size_t size, uint32_t sync_or_async);
    ssize_t (*write)(struct mdf_dev *dev, int off, const void *buf, size_t size, uint32_t sync_or_async);
    int (*ioctl)(struct mdf_dev *dev, int off, int cmd, void *args);
    size_t (*isr)(struct mdf_dev *dev, uint32_t event);
};

struct mdf_dev_flow
{
    struct mdf_list list;

    struct mdf_ringbuf comp;
    size_t comp_count;
};

#define MDF_MAGIC                       (0xdeadbeef)
#define MDF_LOCK_RD                     ((0x01) << 24)
#define MDF_LOCK_WR                     ((0x02) << 24)
#define MDF_LOCK_RDWR                   ((0x03) << 24)

struct mdf_dev
{
    uint32_t magic;
    char name[MDF_NAME_MAX];
    struct mdf_list list;
    struct mdf_list slist;
    void *link;

    uint32_t type;
    uint32_t sflags;
    size_t ref_count;
#if (MDF_CFG_RDWR_LOCK == MDF_CFG_ENABLE)
    volatile uint32_t lock;
#endif /* MDF_CFG_RDWR_LOCK */

    struct
    {
        int desc;
        int (*cb)(int desc, void *args);
    } rd_cb, wr_cb;

    struct mdf_drv *drv;
    const struct mdf_dev_ops *ops;
};

#define MDF_IOCTL_SET_OFFSET        ((0x01|0x80) << 24)
#define MDF_IOCTL_SET_RD_COMP_CB    ((0x02|0x80) << 24)
#define MDF_IOCTL_SET_WR_COMP_CB    ((0x03|0x80) << 24)

#define MDF_IOCTL_GET_OFFSET        ((0x01|0x00) << 24)
#define MDF_IOCTL_GET_RD_COMP_CB    ((0x02|0x00) << 24)
#define MDF_IOCTL_GET_WR_COMP_CB    ((0x03|0x00) << 24)

#define MDF_IOCTL_SET_CONFIG        ((0x01|0x80) << 16)
#define MDF_IOCTL_SET_RD_CB         ((0x02|0x80) << 16)
#define MDF_IOCTL_SET_WR_CB         ((0x03|0x80) << 16)
#define MDF_IOCTL_SET_RD_BUFSZ      ((0x04|0x80) << 16)
#define MDF_IOCTL_SET_WR_BUFSZ      ((0x05|0x80) << 16)

#define MDF_IOCTL_GET_CONFIG        ((0x01|0x00) << 16)
#define MDF_IOCTL_GET_RD_CB         ((0x02|0x00) << 16)
#define MDF_IOCTL_GET_WR_CB         ((0x03|0x00) << 16)
#define MDF_IOCTL_GET_RD_BUFSZ      ((0x04|0x00) << 16)
#define MDF_IOCTL_GET_WR_BUFSZ      ((0x05|0x00) << 16)

#define MDF_ISR_EVENT_RD_INTER      ((0x01) << 24)
#define MDF_ISR_EVENT_WR_INTER      ((0x02) << 24)

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* MDF_DEF_H */
